package com.automannn.seataSamples.business.service.impl;

import com.automannn.seataSamples.api.dto.BusinessDTO;
import com.automannn.seataSamples.api.dto.CommodityDTO;
import com.automannn.seataSamples.api.dto.OrderDTO;
import com.automannn.seataSamples.api.response.BusinessException;
import com.automannn.seataSamples.api.response.ObjectResponse;
import com.automannn.seataSamples.api.response.ResponseStatusEnum;
import com.automannn.seataSamples.api.service.OrderService;
import com.automannn.seataSamples.api.service.StockService;
import com.automannn.seataSamples.business.service.BusinessService;
import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service;

/**
 * @author automannn
 * @Date 2022/3/24
 */
@Service
@Slf4j
public class BusinessServiceImpl implements BusinessService {

    @DubboReference(version = "1.0.0", group = "automannn")
    private StockService stockService;

    @DubboReference(version = "1.0.0",group = "automannn")
    private OrderService orderService;

    private boolean flag;


    @Override
    @GlobalTransactional(timeoutMills = 300000,name="dubbo-gts-seata-automannn1")
    /**
     * 执行成功接口模拟
     */
    public ObjectResponse handleBusinessSuccess(BusinessDTO businessDTO) {
        log.info("开始全局事务，XID = " + RootContext.getXID());

        ObjectResponse objectResponse = new ObjectResponse();

        //第一步，扣减库存
        CommodityDTO commodityDTO = new CommodityDTO();
        commodityDTO.setCommodityCode(businessDTO.getCommodityCode());
        commodityDTO.setCount(businessDTO.getCount());

        ObjectResponse stockResponse = stockService.decreaseStock(commodityDTO);

        //第二步，创建订单
        OrderDTO orderDTO = new OrderDTO();
        orderDTO.setUserId(businessDTO.getUserId());
        orderDTO.setCommodityCode(businessDTO.getCommodityCode());
        orderDTO.setOrderCount(businessDTO.getCount());
        orderDTO.setOrderAmount(businessDTO.getAmount());

        ObjectResponse<OrderDTO> orderDTOObjectResponse = orderService.createOrder(orderDTO);

        if(stockResponse.getStatus()!=200||orderDTOObjectResponse.getStatus()!=200){
            //如果扣减库存，跟创建订单，任意一个步骤出错，则抛出异常，全局事务回滚
            throw new BusinessException(ResponseStatusEnum.FAIL);
        }

        objectResponse.setStatus(ResponseStatusEnum.SUCCESS.getCode());
        objectResponse.setMessage(ResponseStatusEnum.SUCCESS.getMessage());

        return objectResponse;
    }

    @Override
    /**
     * 执行异常，事务模拟
     */
    @GlobalTransactional(timeoutMills = 300000,name="dubbo-gts-seata-automannn2")
    public ObjectResponse handleBusinessFailWithRollback(BusinessDTO businessDTO) {

        log.info("开始全局事务，XID = " + RootContext.getXID());

        ObjectResponse objectResponse = new ObjectResponse();

        //第一步，扣减库存
        CommodityDTO commodityDTO = new CommodityDTO();
        commodityDTO.setCommodityCode(businessDTO.getCommodityCode());
        commodityDTO.setCount(businessDTO.getCount());

        ObjectResponse stockResponse = stockService.decreaseStock(commodityDTO);

        if(!flag){
            throw new RuntimeException("测试抛异常后，分布式事务回滚！");
        }

        //第二步，创建订单
        OrderDTO orderDTO = new OrderDTO();
        orderDTO.setUserId(businessDTO.getUserId());
        orderDTO.setCommodityCode(businessDTO.getCommodityCode());
        orderDTO.setOrderCount(businessDTO.getCount());
        orderDTO.setOrderAmount(businessDTO.getAmount());

        ObjectResponse<OrderDTO> orderDTOObjectResponse = orderService.createOrder(orderDTO);

        if(stockResponse.getStatus()!=200||orderDTOObjectResponse.getStatus()!=200){
            //如果扣减库存，跟创建订单，任意一个步骤出错，则抛出异常，全局事务回滚
            throw new BusinessException(ResponseStatusEnum.FAIL);
        }

        objectResponse.setStatus(ResponseStatusEnum.SUCCESS.getCode());
        objectResponse.setMessage(ResponseStatusEnum.SUCCESS.getMessage());

        return objectResponse;
    }
}
